package com.sca.common.netty.client;

import com.mask.common.core.exception.BaseException;
import com.sca.common.netty.config.NettyProperties;
import com.sca.common.netty.handler.NettyClientHandler;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioSocketChannel;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.handler.timeout.IdleStateHandler;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import javax.annotation.PostConstruct;
import javax.annotation.PreDestroy;
import java.util.concurrent.TimeUnit;

/**
 * Netty客户端
 */
@Slf4j
@Component
public class NettyClient {
    
    @Autowired
    private NettyProperties nettyProperties;
    
    @Autowired
    private NettyClientHandler nettyClientHandler;
    
    private EventLoopGroup group;
    private ChannelFuture channelFuture;
    
    @PostConstruct
    public void start() {
        if (!nettyProperties.isEnabled()) {
            return;
        }
        
        group = new NioEventLoopGroup();
        
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(group)
                    .channel(NioSocketChannel.class)
                    .option(ChannelOption.TCP_NODELAY, true)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel ch) {
                            ch.pipeline()
                                    .addLast(new StringDecoder())
                                    .addLast(new StringEncoder())
                                    .addLast(new IdleStateHandler(
                                            0,
                                            nettyProperties.getClient().getHeartbeatInterval(),
                                            0, TimeUnit.SECONDS))
                                    .addLast(nettyClientHandler);
                        }
                    });
            
            channelFuture = bootstrap.connect(
                    nettyProperties.getClient().getHost(),
                    nettyProperties.getClient().getPort()).sync();
            
            log.info("Netty客户端启动成功，连接服务器：{}:{}",
                    nettyProperties.getClient().getHost(),
                    nettyProperties.getClient().getPort());
            
            channelFuture.channel().closeFuture().sync();
        } catch (Exception e) {
            log.error("Netty客户端启动失败", e);
            throw new BaseException("Netty客户端启动失败：" + e.getMessage());
        }
    }
    
    @PreDestroy
    public void destroy() {
        if (group != null) {
            group.shutdownGracefully();
        }
        log.info("Netty客户端已关闭");
    }
    
    /**
     * 发送消息
     */
    public void sendMessage(String message) {
        if (channelFuture != null && channelFuture.channel().isActive()) {
            channelFuture.channel().writeAndFlush(message);
        } else {
            throw new BaseException("Netty客户端未连接");
        }
    }


//    mask:
//    netty:
//    enabled: true
//    server:
//    port: 8888
//    host: 0.0.0.0
//    heartbeat-enabled: true
//    heartbeat-interval: 30
//    client:
//    host: localhost
//    port: 8888
//    heartbeat-enabled: true
//    heartbeat-interval: 30
//    reconnect-interval: 5
//    max-reconnect-attempts: 3

//    @Service
//    public class MessageService {
//
//        @Autowired
//        private NettyClient nettyClient;
//
//        public void sendMessage(String message) {
//            nettyClient.sendMessage(message);
//        }
//    }
}